<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <svg id="svg"></svg>
</body>

</html>
<script src="http://d3js.org/d3.v6.min.js"></script>
<script>
  let width = 600,
    height = 600;
  let svg = d3.select('#svg').attr('width', width).attr('height', height);
  let g = svg.append('g').attr('transform', `translate(50,50)`);
  let dataset = {
    name: "中国",
    children: [{
        name: "浙江",
        children: [{
            name: "杭州"
          },
          {
            name: "宁波"
          },
          {
            name: "温州"
          },
          {
            name: "绍兴"
          }
        ]
      },
      {
        name: "广西",
        children: [{
            name: "桂林",
            children: [{
                name: "秀峰区"
              },
              {
                name: "叠彩区"
              },
              {
                name: "象山区"
              },
              {
                name: "七星区"
              }
            ]
          },
          {
            name: "南宁"
          },
          {
            name: "柳州"
          },
          {
            name: "防城港"
          }
        ]
      },
      {
        name: "黑龙江",
        children: [{
            name: "哈尔滨"
          },
          {
            name: "齐齐哈尔"
          },
          {
            name: "牡丹江"
          },
          {
            name: "大庆"
          }
        ]
      },
      {
        name: "新疆",
        children: [{
            name: "乌鲁木齐"
          },
          {
            name: "克拉玛依"
          },
          {
            name: "吐鲁番"
          },
          {
            name: "哈密"
          }
        ]
      }
    ]
  };

  //d3.hierarchy 转化数据成为 带有固定属性的新对象
  let hierarchyData = d3.hierarchy(dataset);
  // console.log(hierarchyData)

  // 产生一个创造树状图的函数
  let tree = d3.tree()
    .size([width - 150, height - 150]) // 设置树状图所占位置大小
    // .separation(function (a, b) {
    //   return 0.1
    // })

  let treeData = tree(hierarchyData) // 树状图的数据
  // console.log(treeData)

  let nodes = treeData.descendants(); // 获取所有节点的数据
  let links = treeData.links();
  console.log(nodes, links)


  // 产生一个曲线生成器
  let lineFn = d3.linkHorizontal().x(function (d) {
    // console.log(d)
    return d.y
  }).y(d => d.x)

  let allLines = g.append('g')
    .selectAll('path')
    .data(links)
    .enter()
    .append('path')
    .attr('d', function (d) {
      // console.log(d)
      return lineFn({
        source: {
          x: d.source.x,
          y: d.source.y,
        },
        target: {
          x: d.target.x,
          y: d.target.y,
        }
      })
    })
    .attr('fill', 'none')
    .attr('stroke', '#333')


  let gs = g.append('g').classed('gs', true)
    .selectAll('g')
    .data(nodes)
    .enter()
    .append('g')
    .attr('transform', function (d) {
      return `translate(${d.y},${d.x})`
    })

  gs.append('circle')
    .attr('r', 5)
    .attr('fill', '#fff')
    .attr('stroke', 'blue')

  gs.append('text')
    .attr('x', function (d) {
      return d.children ? -10 : 10
    })
    .attr('text-anchor', function (d) {
      return d.children ? 'end' : "start"
    })
    .attr('y', 5)
    .text(d => d.data.name)

  gs.call(d3.drag().on('start', function (e, d) {
      this.chax = d.x - e.y;
      this.chay = d.y - e.x;
    })
    .on('drag', function (e, d) {
      d.x = e.y - this.chay;
      d.y = e.x - this.chax;
      allLines.attr('d', function (d) {
        return lineFn({
          source: {
            x: d.source.x,
            y: d.source.y,
          },
          target: {
            x: d.target.x,
            y: d.target.y,
          }
        })
      })

      gs.attr('transform', function (d) {
        return `translate(${d.y},${d.x})`
      })
    })
    .on('end', function (e, d) {
      this.chax = null;
      this.chay = null;
    })
  )
</script>